#pragma once

#include <iostream>
#include <string>
#include <vector>
#include <unordered_map>
#include <fstream>
#include <mysql/mysql.h>
#include "../comm/log.hpp"
#include "../comm/util.hpp"

namespace ns_model
{
    using namespace ns_log;
    using namespace ns_util;

    struct Question
    {
        std::string number; // 题号
        std::string name; // 题目名称
        std::string difficulty; // 难度
        int cpu_limit; // cpu 限制
        int mem_limit; // 内存限制

        std::string desc; // 题目描述
        std::string header; // 代码初始状态
        std::string tail; // 测试内容
    };

    const std::string oj_table = "questions";
    const std::string host = "127.0.0.1";
    const std::string user = "oj_client";
    const std::string passwd = "!@#$%^&*()123aacS";
    const std::string db = "oj";
    const int port = 3817;

    // 加载题目信息
    class Model
    {
    public:
        Model() = default;
        ~Model() = default;

        bool QueryMySQL(const std::string& query, std::vector<Question>* questions)
        {
            // 创建mysql句柄
            MYSQL* my = mysql_init(nullptr);
            // 连接数据库
            if(!mysql_real_connect(my, host.c_str(), user.c_str(), passwd.c_str(), db.c_str(), port, nullptr, 0))
            {
                // 连接数据库失败
                LOG(FATAL) << "连接数据库失败，请检查数据库配置！" << std::endl;
                return false;
            }
            // 连接成功
            LOG(INFO) << "连接数据库成功" << std::endl;
            // 设置默认编码格式，不然会出现乱码
            mysql_set_character_set(my, "utf8");
            if(mysql_query(my, query.c_str()) != 0)
            {
                // 成功返回0，失败返回其他
                LOG(WARNING) << "mysql 语句执行失败：" << query << std::endl;
                return false;
            }
            // 获得结果
            MYSQL_RES* res = mysql_store_result(my);
            // 获得行号和列号
            int rows = mysql_num_rows(res);
            int cols = mysql_num_fields(res);

            for(int i = 0; i < rows; ++i)
            {
                MYSQL_ROW row = mysql_fetch_row(res);
                Question q;
                q.number = row[0];
                q.name = row[1];
                q.difficulty = row[2];
                q.desc = row[3];
                q.header = row[4];
                q.tail = row[5];
                q.cpu_limit = atoi(row[6]);
                q.mem_limit = atoi(row[7]);
                questions->push_back(std::move(q));
            }

            // free(res);
            mysql_close(my);
            return true;
        }

        bool GetAllQuestions(std::vector<Question>* ret)
        {
            std::string query = "select * from ";
            query += oj_table;
            return QueryMySQL(query, ret);
        }

        bool GetOneQuestion(const std::string num, Question* q)
        {
            std::string query = "select * from ";
            query += oj_table;
            query += " where id=";
            query += num;
            query += ";";
            std::vector<Question> ret;
            if(!QueryMySQL(query, &ret))
                return false;
            if(ret.size() != 1)
            {
                LOG(WARNING) << "获取单独题目失败" << std::endl;
                return false;
            }
            *q = ret[0];
            return true;
        }
    };
}
